﻿using System;
using System.Data;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Microsoft.SqlServer.Server;

namespace KvDbApi
{
    public static class Usage
    {
        private static readonly SHA256Cng hash32Bytes = new SHA256Cng();

        private const string HexAlphabet = "0123456789ABCDEF";

        public const int ValuePartSize = 8000;

        public const int ValueNotFound = -2147483648;

        private static readonly string[] hexTable = Enumerable.Range(0, 256).Select(v => v.ToString("X2")).ToArray();

        public static string CreateKeyHash(this byte[] keyAsBytes)
        {
            var hash = hash32Bytes.ComputeHash(keyAsBytes);
            
            // HOT PATH CODE. Avoid GC pressure from excess heap allocation.
            unsafe
            {
                var chars = stackalloc char[64];
                var counter = -1;
                for (int i = 0; i < hash.Length; i++)
                {
                    var b = hash[i];
                    chars[++counter] = HexAlphabet[(int)(b >> 4)];
                    chars[++counter] = HexAlphabet[(int)(b & 0xF)];
                }

                return new string(chars, 0, 64);
            }
        }

        internal static void ValidateForBufferOperation(this byte[] buffer, int offset, int count)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException("offset", "The provided offset may not be negative.");
            }

            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("count", "The provided count may not be negative.");
            }

            if (offset >= buffer.Length)
            {
                throw new ArgumentOutOfRangeException("offset", "The provided offset must be less than the length of the provided buffer.");
            }
        }

        internal static NotSupportedException SeekNotSupportedException()
        {
            return new NotSupportedException("Seek is not supported when writing to the underlying key value store.");
        }
    }
}
